Release 10.1A: OpenEdge Development:
Progress Dynamics Basic Development
Server-side validation
Additional validation procedure hooks are designed to be used on the server, where there is free access to the database. This section discusses these entry points. For each of these procedures, remember that the client-side validation entry points described above apply only to a single SDO record. If multiple records are updated, then the client-side validation procedures will be called a number of times. By contrast, the first set of server-side, transaction-level validation routines described below could potentially apply to multiple record updates, and you should write them as
FOREACHblocks on theRowObjUpdtable. As a result, when using the procedures defined below, you must write not only aFOREACHloop on theRowObjUpdtable, but also (if the logic applies only to specific operations such asAdd,Copy,Update, orDelete) a check on each record within the loop that examines the value of the temp-table fieldRowObjUpd.RowMod. The field can have a value ofAforAdd,CforCopy,DforDelete,Ufor anUpdatedrow, and ‘’ (blank) for the before image of an updated row (the field values as read from the database).In the case of an update, another standard
RowObjUpdfield,RowNum, holds a unique row number for each update. The updated row withRowMod=‘U’and the before image of the same row withRowMod=‘’will have the sameRowNumfield. Thus, a block of code that must look at both before and after values will generally be of the form:
Because of the nature of this SDO-specific logic that you must add to the validation, an alternative set of procedure hooks has been defined for Progress Dynamics to handle updates a row at a time, and with buffer names based on the table names. These alternative hooks are discussed in the "New Progress Dynamics validation procedures" section.
preTransactionValidate
preTransactionValidatealways executes on the server, immediately prior to the commencement of a transaction. As such, it can freely read the database, but should do soNO-LOCK. To maximize performance,preTransactionValidateshould be restricted to the type of referential integrity check that can be implemented as a simpleCAN-FINDstatement. For example:
Within this loop, use the
RowObjUpd.RowModfield to determine the type of change for each row (‘A’dd,‘C’opy,‘U’pdate, or‘D’elete).Within
preTransactionValidate,you can physically alter the values that will be written back to the database, if so desired. That is, any changes made to the records in the temp-table will be seen by later procedures within the transaction. Generally,preTransactionValidateis appropriate for code that makes changes to the updated records, and for code that must do comparisons with existing records in the database, but without making changes to them.Keep in mind that you do not want to place code here that might need to look at updated and modified records in one table. That is, some records are in the
RowObjUpdtable as updates and some are unmodified records in the database. For example, if you must total theOrderLinerecords of anOrderin a validation procedure for theOrderLinetable, you do not want to total records in the update temp-table and records in the database together. This will complicate your logic unnecessarily. Such logic should be left to the end of the transaction so that all the records are in the database together.Also, you also do not want to put logic here that does any other database updates. The transaction block is not yet open, and those updates would not be undone if the transaction fails. For example, if the validation logic in an
OrderLineSDO must total all theOrderLinerecords for anOrderand adjust theBalanceof the associatedCustomeraccordingly, and compare that against theCreditLimit, this validation should not be done inpreTransactionValidate.beginTransactionValidate
The
beginTransactionValidateprocedure executes immediately after the start of the transaction, but before any database updates have been performed. There is little to do here except perhaps to gain anEXCLUSIVElock on a parent table to prevent other user sessions from updating the same records (for example, in anOrderLineSDO, lock theOrdertable). In addition, if it is important to do some other validation before anything is actually written to the database, you should do that here.For example, if you want to assure that no other user will attempt to make changes to an order (an
Orderrecord and itsOrderLinerecords) while you are updating any part of the order, you can read theOrderrecord with anEXCLUSIVE-LOCKat the beginning of the transaction in theOrderLineobject. Then, allow the transaction to make changes to one or moreOrderLinerecords.endTransactionValidate
After all updates have been written to the database, but before the transaction is committed,
endTransactionValidateis called. This is the ideal place to perform database cascade operations.One example: Now that all
OrderLinerecords have been updated, recalculate the total amount owing. If done in the write trigger, then this behavior would execute once for every order line. By placing it inendTransactionValidate, the logic is performed once only, whether one, some, or all of the order lines were updated.Another example: On delete of a specific entity you might want to conditionally enforce cascade deletion of child records. It is not possible to put conditional cascade deletion into
Deletetriggers.postTransactionValidate
The
postTransactionValidateprocedure executes once the transaction has been committed, and only if the commit was itself successful. This could be a useful place to write log records, if required. Log records are often written fromWritetriggers and require the triggers to execute within the context of a specific user. If the log were to be written to a database, thenpostTransactionValidatewould have to open a transaction of its own and manage that carefully.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |